# -*- coding: utf-8 -*-

import logging
import json
import hashlib
from datetime import datetime, timedelta
from django.utils.encoding import smart_unicode
from common.bankcard import db as bankcard_db
from common.card_statistics_daily import db as card_stats_daily
from common.card_statistics_weekly import db as card_stats_weekly
from common.card_statistics_monthly import db as card_stats_monthly
from common.bankcard import handler as bankcard_handler
from common.bank_record import db as bank_record_db
from common.utils.decorator import response_wrapper
from common.utils.aes_crypt import aes_encrypt_str
from common.utils.exceptions import ParamError
from common.utils.tz import local_now
from django.views.decorators.http import require_POST, require_GET
from common.cache import redis_cache

_LOGGER = logging.getLogger('hydra')


@require_GET
@response_wrapper
def get_bankcard_info(req):
    query_dct = req.GET.dict()
    data = bankcard_db.get_bankcark_login_info_by_name(query_dct['code'])
    data['accountNumber'] = aes_encrypt_str(data['accountNumber'])
    if not data['loginUsername']:
        data['loginUsername'] = data['accountNumber']
    else:
        data['loginUsername'] = aes_encrypt_str(data['loginUsername'])
    data['loginPassword'] = aes_encrypt_str(data['loginPassword'])
    data['payPassword'] = aes_encrypt_str(data['payPassword'])
    data['ukeyPassword'] = aes_encrypt_str(data['ukeyPassword'])
    data['Status'] = data['status']
    data['Balance'] = data['balance']

    _LOGGER.info('get_bankcard_info: %s', query_dct['code'])
    return data


@require_GET
@response_wrapper
def get_last_trans_info(req):
    query_dct = req.GET.dict()
    t = bank_record_db.get_last_card_transaction_time(query_dct['code'])
    if t:
        transaction_time = t.strftime('%Y-%m-%d %H:%M:%S')
    else:
        transaction_time = (local_now() -
                            timedelta(days=7)).strftime('%Y-%m-%d 00:00:00')
    _LOGGER.info('get_last_trans_info: %s, transaction_time: %s',
                 query_dct, transaction_time)
    return {'transaction_time': transaction_time}


_KEY = '6df03bc8d7d04348a61f8042b8d457d1'


def _verify_sign(d):
    s = str(d['balance']) + d['code'] + d['time'] + _KEY
    m = hashlib.md5()
    m.update(s)
    sign = m.hexdigest().upper()
    _LOGGER.info('_verify_sign: %s, gen_sign: %s, s: %s', d['sign'], sign, s)
    if sign != d['sign']:
        raise ParamError('sign error')


@require_POST
@response_wrapper
def upload_bankcard_record(req):
    _LOGGER.info('upload_bankcard_record: %s', req.body)
    param_dct = json.loads(smart_unicode(req.body))
    _verify_sign(param_dct)
    bank_card = bankcard_db.get_bankcard_by_name(param_dct['code'])
    for record in reversed(param_dct['records']):
        trans_time = datetime.strptime(record['transaction_time'],
                                       '%Y-%m-%d %H:%M:%S')
        record['transaction_time'] = trans_time
        record_id = bank_record_db.insert_bank_record(record, bank_card)
        _LOGGER.info('upload_bankcard_record record_id: %s', record_id)

    bankcard_db.update_bankcard_balance(
        param_dct['code'], float(str(param_dct['balance']).replace(',', '')))

    bankcard_handler.card_balance_alert(bank_card.id, req.META['HTTP_HOST'])
    return {'result': 'ok'}


def _verify_sms_warning_sign(d):
    s = d['code'] + d['time'] + _KEY
    m = hashlib.md5()
    m.update(s)
    sign = m.hexdigest().upper()
    _LOGGER.info('_verify_sms_warning_sign: %s, gen_sign: %s, s: %s',
                 d['sign'], sign, s)
    if sign != d['sign']:
        raise ParamError('sign error')


@require_GET
@response_wrapper
def sms_verify_warning(req):
    query_dct = req.GET.dict()
    _LOGGER.info('sms_verify_warning: %s', query_dct)
    _verify_sms_warning_sign(query_dct)
    vcode = bankcard_handler.get_sms_vcode(query_dct['code'], query_dct['time'])
    _LOGGER.info('sms_verify_warning vcode: %s', vcode)
    if vcode == '':
        return {'result': 'no', 'vcode': vcode}
    else:
        return {'result': 'ok', 'vcode': vcode}


def _verify_card_frosen_sign(d):
    s = d['code'] + d['time'] + _KEY
    m = hashlib.md5()
    m.update(s)
    sign = m.hexdigest().upper()
    if sign != d['sign']:
        raise ParamError('sign error')


@require_GET
@response_wrapper
def card_frozen_warning(req):
    query_dct = req.GET.dict()
    _LOGGER.info('card_frozen_warning: %s', query_dct)
    _verify_card_frosen_sign(query_dct)
    return {'result': 'ok'}


@require_GET
@response_wrapper
def card_online_heart_beat(req):
    query_dct = req.GET.dict()
    _verify_card_frosen_sign(query_dct)
    redis_cache.update_bankcard_online_status(query_dct['code'])
    card = bankcard_db.get_bankcard_by_name(query_dct['code'])
    status = 'enable' if card.status == 1 else 'disable'
    _LOGGER.info('card_online_heart_beat: %s, card_status: %s, balance: %s',
                 query_dct, status, card.balance)
    return {'result': 'ok', 'status': status, 'balance': card.balance}


@require_GET
@response_wrapper
def get_card_stats_daily(req):
    query_dct = req.GET.dict()
    daily_stats = card_stats_daily.get_cards_statistics(query_dct['card_code'])
    if daily_stats:
        return daily_stats.as_dict()
    else:
        return {'result': 'no record found'}


@require_GET
@response_wrapper
def get_card_stats_weekly(req):
    query_dct = req.GET.dict()
    weekly_stats = card_stats_weekly.get_cards_statistics(
        query_dct['card_code'])
    if weekly_stats:
        return weekly_stats.as_dict()
    else:
        return {'result': 'no record found'}


@require_GET
@response_wrapper
def get_card_stats_monthly(req):
    query_dct = req.GET.dict()
    monthly_stats = card_stats_monthly.get_cards_statistics(
        query_dct['card_code'])
    if monthly_stats:
        return monthly_stats.as_dict()
    else:
        return {'result': 'no record found'}


@require_GET
@response_wrapper
def send_card_status_warning(req):
    query_dct = req.GET.dict()
    card = bankcard_db.get_bankcard_by_name(query_dct['code'])
    status = ''

    _LOGGER.info('card_status_warning: %s', query_dct)

    if 'status' in query_dct:
        status = query_dct['status']

    if card:
        if len(card.account_number) > 7:
            star_length = len(card.account_number) - 7
            stars = '*' * star_length
            card.account_number = card.account_number[0:3] + stars + card.account_number[-4:]
        elif len(card.account_number) >= 4:
            star_length = len(card.account_number) - 2
            stars = '*' * star_length
            card.account_number = card.account_number[0:1] + stars + card.account_number[-2:]
        bankcard_handler.__send_card_status_warning(card, status)
        return {'result': 'ok'}
